/*
 * Copyright (C) 2010 Rodion Volkov (volkov.rodion@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.rchik.divermate;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Paint.Align;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextPaint;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.DatePicker.OnDateChangedListener;

import com.rchik.divermate.DiveLogElement.LogTypes;

public class FacebookDataPostDialog extends Activity implements OnClickListener, FacebookPhotoUploadListener, OnDateChangedListener {
	
	private final int SELECT_PRIMARY_IMAGE = 1;
	private final int SELECT_SECONDARY_IMAGE = 2;
	private final int SELECT_TERTIARY_IMAGE = 3;
	private ImageView primaryImageView;
	private ImageView secondaryImageView;
	private ImageView tertiaryImageView;
	private Uri primaryImage;
	private Uri secondaryImage;
	private Uri tertiaryImage;
	private EditText locationEditText;
	private ArrayList<DiveLogElement> diveLog;
	private DatePicker datePicker;
	private static final int textLeft = 25;
	private static final int textTop = 132;
	private static final int textSize = 24;
	private static final int topLine = 230;
	private static final int bottomLine = 320;
	private FacebookPhotoUploader facebookPhotoUploader;
	private int selectedYear;
	private int selectedMonth;
	private int selectedDayOfMonth;
	private int currentLevel;
	private static File uploadFile;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.post_dive_facebook);
		
		facebookPhotoUploader = new FacebookPhotoUploader(this);
        facebookPhotoUploader.setAPP_ID("7500ea1720b00326183beca206832aa4");
        facebookPhotoUploader.setListener(this);
		
		((ImageButton)findViewById(R.id.OkButton)).setOnClickListener(this);
		((ImageButton)findViewById(R.id.CancelButton)).setOnClickListener(this);
		primaryImageView = (ImageView)findViewById(R.id.PrimaryImageView);
		primaryImageView.setOnClickListener(this);
		secondaryImageView = (ImageView)findViewById(R.id.SecondaryImageView);
		secondaryImageView.setOnClickListener(this);
		tertiaryImageView = (ImageView)findViewById(R.id.TertiaryImageView);
		tertiaryImageView.setOnClickListener(this);
		locationEditText = (EditText)findViewById(R.id.LocationEditText);
		datePicker = (DatePicker)findViewById(R.id.DatePicker);
		
		final Calendar c = Calendar.getInstance(); 
        selectedYear = c.get(Calendar.YEAR); 
        selectedMonth = c.get(Calendar.MONTH); 
        selectedDayOfMonth = c.get(Calendar.DAY_OF_MONTH);
		
		datePicker.init(selectedYear, selectedMonth, selectedDayOfMonth, this);
		diveLog = DivingMenu.getDiveLog();
		
		currentLevel = getIntent().getIntExtra("currentLevel", -1);
	}
	
	public void Initialize()
	{
	}

	@Override
	public void onClick(View arg0) {

		switch( arg0.getId() )
		{
			case R.id.OkButton:
			{
				PostToFacebook();
				
				break;
			}
			
			case R.id.CancelButton:
			{
				finish();
				
				break;
			}
			
			case R.id.PrimaryImageView:
			{
				startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI),
						SELECT_PRIMARY_IMAGE);
				
				break;
			}
			
			case R.id.SecondaryImageView:
			{
				startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI),
						SELECT_SECONDARY_IMAGE);
				
				break;
			}
			
			case R.id.TertiaryImageView:
			{
				startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI),
						SELECT_TERTIARY_IMAGE);
				
				break;
			}
		}
	}
	
	private void PostToFacebook()
	{
	    final PhotoUploadProgressDialog pdialog = new PhotoUploadProgressDialog(this, 
				getResources().getString(R.string.please_wait), 
				getResources().getString(R.string.creating_dive_log));
	    
	    pdialog.show();
	    
	    new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				final File file;
				try {
					file = File.createTempFile("dive_log", null);
				} catch (IOException e1) {
					e1.printStackTrace();
					
					statusMessage(e1.getMessage());
					
					return;
				}
				
				FacebookDataPostDialog.setUploadFile(file);
				
				try
				{
				
					Bitmap bitmap;
				    Bitmap baseBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dive_log_basis);
				    
				    final Bitmap mutable = Bitmap.createBitmap(baseBitmap.getWidth(), baseBitmap.getHeight(), baseBitmap.getConfig());
				    Canvas canvas = new Canvas(mutable);
				    canvas.drawBitmap(baseBitmap, new Matrix(), null);
				    
				    Matrix matrix;
				    float scaleRatio,sry;
				    
				    if ( primaryImage != null )
				    {
				    	bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(primaryImage));
					    matrix = new Matrix();
					    scaleRatio = 200f/bitmap.getWidth();
					    sry = 200f/bitmap.getWidth();
					    matrix.postScale(scaleRatio, sry);
					    matrix.postRotate(15);
					    matrix.postTranslate(80, 350);
					    canvas.drawBitmap(bitmap, matrix, null);
					    bitmap.recycle();
				    }
				    
				    if ( secondaryImage != null )
				    {
				    	bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(secondaryImage));
					    matrix = new Matrix();
					    scaleRatio = 200f/bitmap.getWidth();
					    sry = 200f/bitmap.getWidth();
					    matrix.postScale(scaleRatio, sry);
					    matrix.postTranslate(370, 370);			    
					    canvas.drawBitmap(bitmap, matrix, null);
					    bitmap.recycle();
				    }
				    
				    if (tertiaryImage != null)
				    {
				    	bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(tertiaryImage));
					    matrix = new Matrix();
					    scaleRatio = 200f/bitmap.getWidth();
					    sry = 200f/bitmap.getWidth();			    
					    matrix.postScale(scaleRatio, sry);
					    matrix.postRotate(-25);
					    matrix.postTranslate(180, 410);			    
					    canvas.drawBitmap(bitmap, matrix, null);
					    bitmap.recycle();
				    }
				    
				    TextPaint tp = new TextPaint(Paint.ANTI_ALIAS_FLAG);
				    tp.setColor(Color.WHITE);
				    tp.setTypeface(Typeface.SANS_SERIF);
				    
				    drawTitle(canvas, tp);
				    
				    drawLocation(canvas, tp, locationEditText.getText().toString());
				    
				    DateFormat format = DateFormat.getDateInstance();
				    Date date = new Date(selectedYear-1900, selectedMonth, selectedDayOfMonth);
				    drawDate(canvas, tp, format.format(date));
				    
				    drawMaxDiveDepth(canvas, tp, findBiggestDepth(diveLog));
				    
				    drawDiveGraph(canvas, tp, diveLog);
				    
				    //file.createNewFile();
				    
				    final FileOutputStream fos = new FileOutputStream(file);						
				
					mutable.compress(CompressFormat.PNG, 100, fos);
				
					fos.flush();
					fos.close();
					
					final FileInputStream fis = new FileInputStream(file);
					
					FacebookDataPostDialog.this.runOnUiThread(new Runnable() {
						
						@Override
						public void run() {
							facebookPhotoUploader.uploadPhoto(pdialog, fis, file.length(), "Divermate", "Dive");									}
					});
				}
				catch (Exception e)
				{
					e.printStackTrace();
					
					pdialog.dismiss();
					
					statusMessage(e.getMessage());
					
					file.delete();
				}
			}
		}).start();
	                
	    //statusView.setText("COMPLETE");
//      AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(selectedImage, "r");
//            
//		facebookPhotoUploader.uploadPhoto(fd.createInputStream(), fd.getLength(), "Divermate", "Dive");
	}
	
	private void drawDiveGraph(Canvas canvas, TextPaint tp,
			ArrayList<DiveLogElement> log) {
		
		int divider = 0;
		int maxWidth = 500;
		
		for ( int i = 0; i < log.size(); i++ )
		{
			switch ( log.get(i).getLogType() )
			{
				case Dive:
				{
					divider +=4;
					
					break;
				}
				case Rest:
				{
					divider += 2;
					
					break;
				}
				case Final:
				{
					divider += 1;
					
					break;
				}
			}
		}
		
		int particleWidth = (maxWidth/divider)>50 ? 50 : maxWidth/divider;
		int totalFrameWidth = particleWidth*divider;
		int leftEdge = 300 - (totalFrameWidth / 2);
		
		for ( int j = 0; j < log.size(); j++ )
		{
			DiveLogElement element = log.get(j);
			switch ( element.getLogType() )
			{
				case Dive:
				{
					drawDive(canvas, tp, element, 
							leftEdge, particleWidth);
					
					leftEdge += 4*particleWidth;
					
					break;
				}
				case Rest:
				{
					drawRest(canvas, tp, element, 
							leftEdge, particleWidth);
					
					leftEdge += 2*particleWidth;
					
					break;
				}
				case Final:
				{
					drawFinal( canvas, tp, element, 
							leftEdge, particleWidth);
					
					break;
				}
			}
		}
		
		DiveLogElement finalElement = new DiveLogElement(currentLevel);
		
		drawFinal(canvas, tp, finalElement, leftEdge, particleWidth);
	}

	private void drawFinal(Canvas canvas, 
							TextPaint tp, 
							DiveLogElement element, 
							int leftEdge, 
							int particleWidth) {
		Paint linePaint = new Paint();
		linePaint.setStrokeWidth(3);
		
		linePaint.setColor(Color.WHITE);
		
		canvas.drawLine(leftEdge, topLine, leftEdge+particleWidth, topLine, linePaint);
		
		
		drawLevelRectangle(canvas, element, leftEdge, tp);
	}

	private void drawRest(Canvas canvas, 
							TextPaint tp, 
							DiveLogElement element, 
							int leftEdge, 
							int particleWidth) {
		Paint linePaint = new Paint();
		linePaint.setStrokeWidth(3);
		
		linePaint.setColor(Color.WHITE);
		
		canvas.drawLine(leftEdge, topLine, leftEdge+particleWidth*2, topLine, linePaint);
		
		drawLevelRectangle(canvas, element, leftEdge, tp);
		
		tp.setColor(Color.rgb(0x39, 0x51, 0x6b));
		tp.setTextAlign(Align.CENTER);
		canvas.drawText("Rest", leftEdge+(int)(1.5*particleWidth), topLine + 60, tp);
		canvas.drawText((String)element.getParams().get("Time"), leftEdge+(int)(1.5*particleWidth), topLine - 2, tp);
		tp.setTextAlign(Align.LEFT);
		tp.setColor(Color.WHITE);
	}

	private void statusMessage( String message )
	{
		final String toastMessage = message;
		final Context context = this;
		
		this.runOnUiThread(new Runnable() {
			
			@Override
			public void run() {
				Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show();
			}
		});
	}
	
	private void drawDive(Canvas canvas, 
								TextPaint tp, 
								DiveLogElement element, 
								int leftEdge, 
								int particleWidth) {
		Paint linePaint = new Paint();
		linePaint.setStrokeWidth(3);
		
		linePaint.setColor(Color.WHITE);
		
		canvas.drawLine(leftEdge, topLine, leftEdge+particleWidth, topLine, linePaint);
		canvas.drawLine(leftEdge+particleWidth, bottomLine, leftEdge+particleWidth*4, bottomLine, linePaint);
		canvas.drawLine(leftEdge+particleWidth, topLine - 1, leftEdge+particleWidth, bottomLine + 2, linePaint);
		canvas.drawLine(leftEdge+particleWidth*4, topLine - 1, leftEdge+particleWidth*4, bottomLine + 2, linePaint);
		
		drawLevelRectangle(canvas, element, leftEdge, tp);
		
		tp.setColor(Color.rgb(0x39, 0x51, 0x6b));
		tp.setTextAlign(Align.CENTER);
		canvas.drawText("Dive", leftEdge+(int)(2.5*particleWidth), topLine + 25, tp);
		String depthMetric = (Integer)element.getParams().get("DepthMetric") == 0?"M":"Ft";
		canvas.drawText((Integer)element.getParams().get("Depth")+depthMetric, leftEdge+(int)(2.5*particleWidth), topLine + 55, tp);
		canvas.drawText((String)element.getParams().get("Time")+"MIN", leftEdge+(int)(2.5*particleWidth), bottomLine - 7, tp);
		tp.setTextAlign(Align.LEFT);
		tp.setColor(Color.WHITE);
	}

	private void drawLevelRectangle(Canvas canvas, DiveLogElement element, int leftEdge, TextPaint tp)
	{
		Paint fillPaint = new Paint();
		if (element.getInitialLevel() > 0)
		{
			fillPaint.setColor(LevelIndicator.levelColors[element.getInitialLevel()]);
		}
		else
		{
			fillPaint.setColor(Color.GREEN);
		}
		
		int rectHeight = (int)(tp.getFontMetrics().bottom + tp.getFontMetrics().top);
		
		canvas.drawRect(new Rect(leftEdge + 5, topLine + rectHeight - 1, leftEdge+35, topLine - 1 ), fillPaint);
		
		if ( element.getInitialLevel() != -1 )
		{
			float[] widths = new float[1];
			String levelString = (char)('A'+element.getInitialLevel())+"";
			tp.getTextWidths(levelString, widths);
			canvas.drawText(levelString, leftEdge + (20 - (int)(widths[0]/2)), topLine - 1, tp);
		}
		else
		{
			float[] widths = new float[1];
			tp.getTextWidths("0", widths);
			canvas.drawText("0", leftEdge + (20 - (int)(widths[0]/2)), topLine - 1, tp);
		}
	}
	
	private void drawMaxDiveDepth(Canvas canvas, TextPaint tp, String maxDepth) {
		tp.setTextSize(textSize);
	    
	    String text = getResources().getString(R.string.maximum_depth)+" " + maxDepth;
	    float[] widths = new float[text.length()];
	    tp.getTextWidths(text, widths);
	    float[] pt = new float[2];
	    float[] textCoords = new float[text.length()*2];
	    
	    pt[0] = textLeft;
	    pt[1] = textTop+tp.getFontSpacing()*2;
	    
	    for ( int j = 0; j < text.length(); j++ )
	    {
	    	textCoords[j*2] = pt[0];
	    	textCoords[j*2+1] = pt[1];
	    	pt[0] += widths[j];
	    }
	    canvas.drawPosText(text, textCoords, tp);
	}

	private void drawDate(Canvas canvas, TextPaint tp, String date) {
		tp.setTextSize(textSize);
	    
	    String text = getResources().getString(R.string.date) +" "+ date;
	    float[] widths = new float[text.length()];
	    tp.getTextWidths(text, widths);
	    float[] pt = new float[2];
	    float[] textCoords = new float[text.length()*2];
	    
	    pt[0] = textLeft;
	    pt[1] = textTop+tp.getFontSpacing();
	    
	    for ( int j = 0; j < text.length(); j++ )
	    {
	    	textCoords[j*2] = pt[0];
	    	textCoords[j*2+1] = pt[1];
	    	pt[0] += widths[j];
	    }
	    canvas.drawPosText(text, textCoords, tp);
	}

	private void drawLocation(Canvas canvas, TextPaint tp, String location) {
		tp.setTextSize(textSize);
	    
	    String text = getResources().getString(R.string.location) +" "+ location;
	    float[] widths = new float[text.length()];
	    tp.getTextWidths(text, widths);
	    float[] pt = new float[2];
	    float[] textCoords = new float[text.length()*2];
	    
	    pt[0] = textLeft;
	    pt[1] = textTop;
	    
	    for ( int j = 0; j < text.length(); j++ )
	    {
	    	textCoords[j*2] = pt[0];
	    	textCoords[j*2+1] = pt[1];
	    	pt[0] += widths[j];
	    }
	    canvas.drawPosText(text, textCoords, tp);
	}

	private void drawTitle(Canvas canvas, TextPaint tp) {
		tp.setTextSize(52);
	    
		String title = getResources().getString(R.string.dive_log);
		
	    float[] widths = new float[title.length()];
	    tp.getTextWidths(title, widths);
	    float[] pt = new float[2];
	    float[] textCoords = new float[title.length()*2];
	    
	    pt[0] = 25;
	    pt[1] = 65;
	    
	    for ( int j = 0; j < title.length(); j++ )
	    {
	    	textCoords[j*2] = pt[0];
	    	textCoords[j*2+1] = pt[1];
	    	pt[0] += widths[j];
	    }
	    canvas.drawPosText(title, textCoords, tp);
	}
	
	private String findBiggestDepth(ArrayList<DiveLogElement> diveLog) 
	{
		int maxDepth = 0;
		Iterator<DiveLogElement> iterator = diveLog.iterator();
		
		while (iterator.hasNext())
		{
			DiveLogElement element = iterator.next();
			if ( element.getLogType() == LogTypes.Dive )
			{
				int currentDepth = (Integer)element.getParams().get("Depth");
				
				if ( currentDepth > maxDepth )
				{
					maxDepth = currentDepth;
				}
			}
		}
		
		return ""+maxDepth;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		if ( data != null )
		{
			ImageView currentImageView = null;
			Uri selectedImage = data.getData();
			
			switch( requestCode)
			{
				case SELECT_PRIMARY_IMAGE:
				{
					currentImageView = primaryImageView;
					primaryImage = selectedImage;
					break;
				}
				case SELECT_SECONDARY_IMAGE:
				{
					currentImageView = secondaryImageView;
					secondaryImage = selectedImage;
					break;
				}
				case SELECT_TERTIARY_IMAGE:
				{
					currentImageView = tertiaryImageView;
					tertiaryImage = selectedImage;
					break;
				}
				default:
					break;
			}	
			
		    if (resultCode == Activity.RESULT_OK) {
		    	try
		    	{
		    		Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage));
		    		Matrix matrix = new Matrix();
		    		float scaleRatio = 72f/bitmap.getWidth();
				    float sry = 72f/bitmap.getWidth();
				    matrix.postScale(scaleRatio, sry);
				    currentImageView.setImageBitmap(Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,false));
				    bitmap.recycle();
		    	}
		    	catch (Exception e)
		    	{
		    		e.printStackTrace();
		    	}
		    }
		}
	}

	@Override
	public void onPhotoUploadFailed(ErrorCodes errorCode, String message) {
		statusMessage(message);
		
		if ( uploadFile != null )
		{
			uploadFile.delete();
			uploadFile = null;
		}
	}

	@Override
	public void onPhotoUploadSuccess(String id) {
		
		if ( uploadFile != null )
		{
			uploadFile.delete();
			uploadFile = null;
		}
		
		setResult(Activity.RESULT_OK);
		
		finish();
	}

	@Override
	public void onDateChanged(DatePicker arg0, int year, int monthOfYear, int dayOfMonth) {
		selectedYear = year;
		selectedMonth = monthOfYear;
		selectedDayOfMonth = dayOfMonth;
	}

	public static void setUploadFile(File uploadFile) {
		FacebookDataPostDialog.uploadFile = uploadFile;
	}
}
